#include "lua_handler.h"

using namespace G3;

const long G3::LuaBufferSize = 10240;
G3::LUA_HANDLER G3::MainLuaHandler;

//==============================================================================
// Constructors
//==============================================================================
G3::LUA_HANDLER::LUA_HANDLER () {
	Log = &MainLog;
	Init ();
}

//==============================================================================
// Destructors
//==============================================================================
G3::LUA_HANDLER::~LUA_HANDLER () {
	if (LuaState != NULL)
		lua_close (LuaState);
}

//==============================================================================
// Initializes Lua
//==============================================================================
bool G3::LUA_HANDLER::Init () {
	LuaState = lua_open ();

	if (!LuaState) {
		Log->Report ("ERROR: LUA_HANDLER::Init: Failed to initialize Lua..\n");
		return false;
	}
	return true;
}

//==============================================================================
// Loads and executes a Lua script from a stream
//==============================================================================
int G3::LUA_HANDLER::Execute (STREAM *aStream) {
	lua_Number Result = 0;

	if (aStream == NULL) {
	    if (Log)
            Log->Report ("ERROR: LUA_HANDLER::Execute: Stream argument is a NULL pointer..\n");
        return -1;
	}

	if (!LuaState)
		return -1;

	if (lua_load (LuaState, LuaStreamReader, aStream, aStream->fileName.c_str ()) == 0) {
		// No arguments, 1 return value
		if (lua_pcall (LuaState, 0, 1, 0) == 0)
			Result = lua_tonumber (LuaState, lua_gettop (LuaState));
	} else
		Log->Report ("LUA_HANDLER::Execute: Lua error:\n%s\n", lua_tostring (LuaState, lua_gettop (LuaState)));

	lua_pop (LuaState, 1);

	return (int) Result;
}

//==============================================================================
// Loads standard function / variable bindings
//==============================================================================
void G3::LUA_HANDLER::LoadStdlibs () {
	if (!LuaState)
		return;

	luaL_openlibs (LuaState);
}

//==============================================================================
// Lua reader callback for stream reading
//==============================================================================
const char *G3::LuaStreamReader (lua_State *aState, void *aUserData, size_t *aSize) {
	Assert (aState, "LuaStreamReader: State argument is a NULL pointer");
	Assert (aUserData, "LuaStreamReader: UserData argument is a NULL pointer");
	Assert (aSize, "LuaStreamReader: Size argument is a NULL pointer");

	STREAM *Stream = (STREAM *) aUserData;

	if (Stream->EndOfFile ())
		return NULL;

	static char Script [LuaBufferSize + 1];

	memset (Script, 0, LuaBufferSize);

	*aSize = (size_t) Stream->Read ((byte *) Script, LuaBufferSize);

	if (*aSize == 0)
        return NULL;

	return Script;
}
